using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Mail;
using System.Text.RegularExpressions;

namespace EventLogMailer
{
    public class MailRule
    {
        public string SourceNameIncludeRegex { get; set; }
        public string SourceNameExcludeRegex { get; set; }
        public string Recipient { get; set; }
        public string EntryTypes { get; set; }

        public MailRule()
        {
        }

        public MailRule(string recipient, string sourceNameIncludeRegex = null, string sourceNameExcludeRegex = null, params EventLogEntryType[] entryTypes)
        {
            this.SourceNameIncludeRegex = sourceNameIncludeRegex;
            this.SourceNameExcludeRegex = sourceNameExcludeRegex;
            this.Recipient = recipient;
            if (entryTypes.Length == 0)
            {
                entryTypes = this.GetEntryTypes().ToArray();
            }

            this.EntryTypes = string.Join(",", entryTypes.Select(e => e.ToString()).ToArray());
        }

        public IEnumerable<EventLogEntryType> GetEntryTypes()
        {
            if (string.IsNullOrEmpty(this.EntryTypes))
            {
                return new[] { EventLogEntryType.Error, EventLogEntryType.Warning };
            }

            var entryTypes = new List<EventLogEntryType>();
            var parts = this.EntryTypes.Split(new[] { ',', ';' }).Select(p => p.Trim()).Where(p => string.IsNullOrEmpty(p) == false);
            foreach (var part in parts)
            {
                EventLogEntryType entryType;
                if (Enum.TryParse(part, out entryType) == false)
                {
                    throw new FormatException(string.Format("Invalid value '{0}' for {1}.", part, typeof(EventLogEntryType)));
                }

                entryTypes.Add(entryType);
            }

            return entryTypes;
        }

        public void Validate()
        {
            if (string.IsNullOrEmpty(Recipient))
            {
                throw new InvalidOperationException("Recipient cannot be empty");
            }


            #pragma warning disable 168
            //check for valid email address
            var recipient = new MailAddress(Recipient);
            #pragma warning restore 168

            this.GetEntryTypes();
            //check regex
            this.Matches("asd");
        }

        private bool Matches(string sourceName)
        {
            
            if (string.IsNullOrEmpty(this.SourceNameIncludeRegex) || this.SourceNameIncludeRegex == "*")
            {
                return IsExcluded(sourceName) == false;
                
            }

            if(Regex.IsMatch(sourceName, this.SourceNameIncludeRegex)==false)
            {
                return false;
            }

            return IsExcluded(sourceName) == false;
        }

        private bool IsExcluded(string sourceName)
        {
            if(string.IsNullOrEmpty(SourceNameExcludeRegex))
            {
                return false;
            }

            return Regex.IsMatch(sourceName, SourceNameExcludeRegex);
        }

        public bool Matches(EventLogEntry entry)
        {
            return this.GetEntryTypes().Contains(entry.EntryType) && Matches(entry.Source);
        }
    }
}